package core

import (
	"fmt"
	"github.com/glebarez/sqlite"
	"github.com/sirupsen/logrus"
	"go_blok/server/global"
	"go_blok/server/model"
	"gorm.io/driver/mysql"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
	"time"
)

// 初始化数据库
func InitGorm() (database *gorm.DB) {
	db := global.Config.DB
	var (
		dialector gorm.Dialector
		dsn       string
	)
	switch db.Mode {
	case "mysql":
		dsn = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
			db.User,
			db.Password,
			db.Host,
			db.Port,
			db.DbName,
		)
		dialector = mysql.Open(dsn)
	case "pgsql":
		dsn = fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=disable TimeZone=Asia/Shanghai",
			db.Host,
			db.User,
			db.Password,
			db.DbName,
			db.Port,
		)
		dialector = postgres.Open(dsn)
	case "sqlite":
		dialector = sqlite.Open(db.Host)
	case "":
		logrus.Warnf("未配置数据库连接")
		return nil
	default:
		logrus.Fatalf("不支持的数据库mode配置")
	}

	database, err := gorm.Open(dialector, &gorm.Config{
		DisableForeignKeyConstraintWhenMigrating: true, // 不生成实体外键
	})
	if err != nil {
		logrus.Fatalf("数据库连接失败 %s", err)
	}
	// 配置连接池
	sqlDB, err := database.DB()
	if err != nil {
		logrus.Fatalf("获取数据库连接失败 %s", err)
	}
	err = sqlDB.Ping()
	if err != nil {
		logrus.Fatalf("数据库连接失败 %s", err)
	}
	// 设置连接池
	sqlDB.SetMaxIdleConns(10)
	sqlDB.SetMaxOpenConns(100)
	sqlDB.SetConnMaxLifetime(time.Hour)
	logrus.Info(db.Mode, "数据库连接成功")
	return database
}

// InitTable 初始化表
func InitTable(db *gorm.DB) {
	// 防 nil 保护：避免 db 为空时调用方法导致 panic
	if db == nil {
		logrus.Fatal("InitTable: 数据库连接(db)不能为空")
		return
	}

	// 获取数据库类型（从全局配置读取，与 InitGorm 保持一致）
	dbMode := global.Config.DB.Mode

	// 定义模型与其注释的映射
	migrations := []struct {
		model   interface{}
		comment string
	}{
		{model.UserModel{}, "用户表，存储用户信息"},
		{model.RoleModel{}, "角色表，存储角色信息"},
		{model.MenuModel{}, "菜单表，存储菜单信息"},
	}

	// 逐个迁移表
	for _, migration := range migrations {
		// 根据数据库类型生成适配的表选项（避免 MySQL 特有配置在其他数据库报错）
		var tableOptions string
		switch dbMode {
		case "mysql":
			// MySQL 表选项：引擎、字符集、注释
			tableOptions = fmt.Sprintf("ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='%s'", migration.comment)
		case "pgsql":
			// PostgreSQL 仅支持注释（无 ENGINE 配置）
			tableOptions = fmt.Sprintf("COMMENT '%s'", migration.comment)
		case "sqlite":
			// SQLite 无需额外表选项（默认配置即可）
			tableOptions = ""
		default:
			logrus.Warnf("未知数据库类型 [%s]，将使用默认表选项", dbMode)
			tableOptions = ""
		}

		// 执行迁移（仅当表选项非空时设置，避免无效配置）
		tx := db
		if tableOptions != "" {
			tx = db.Set("gorm:table_options", tableOptions)
		}

		// 执行自动迁移并处理错误
		if err := tx.AutoMigrate(migration.model); err != nil {
			logrus.Errorf("表 [%T] 迁移失败: %v", migration.model, err)
		} else {
			logrus.Infof("表 [%T] 迁移成功（注释: %s）", migration.model, migration.comment)
		}
	}
}
